package com.bora_bandeco;

import static com.bora_bandeco.CommonUtilities.SENDER_ID;
import static com.bora_bandeco.CommonUtilities.GCM_NOTIFICATION_REGISTRO;
import static com.bora_bandeco.CommonUtilities.GCM_NOTIFICATION_NOVO_CONVITE;
import static com.bora_bandeco.CommonUtilities.GCM_NOTIFICATION_RESPOSTA_CONVITE;
import static com.bora_bandeco.CommonUtilities.PROPERTY_APP_VERSION;
import static com.bora_bandeco.CommonUtilities.PROPERTY_FOTO_CODIFICADA;
import static com.bora_bandeco.CommonUtilities.PROPERTY_ID;
import static com.bora_bandeco.CommonUtilities.PROPERTY_NOME;
import static com.bora_bandeco.CommonUtilities.PROPERTY_NUMERO_TELEFONE;
import static com.bora_bandeco.CommonUtilities.PROPERTY_REG_ID;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import net.londatiga.android.ActionItem;
import net.londatiga.android.QuickAction;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.AnimationDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import com.actionbarsherlock.app.ActionBar;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.slidingmenu.lib.SlidingMenu;
import com.slidingmenu.lib.app.SlidingFragmentActivity;

public class CardapioActivity extends SlidingFragmentActivity {
	static final String TAG = "GCMDemo";
    
    private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
	
	public FragmentManager mFragmentManager;
	public QuickAction quickAction;

    GoogleCloudMessaging gcm;
    
    final BroadcastReceiver registroReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
        	View v = findViewById(R.id.buttonlayout);
            v.setVisibility(View.VISIBLE);
            
            if (intent.hasExtra(PROPERTY_ID)) {
            	int id = intent.getIntExtra(PROPERTY_ID, 0);
                
                // Guarda os dados do usuário nas preferências locais do aparelho
                storeUserData(CardapioActivity.this, id);
            }
            // Chama o update do cardápio via internet
        	receberCardapio();

    		//Quando termina o registro, é hora de buscar os contatos do aplicativo
    		ContatosFetcher fetcher = new ContatosFetcher(CardapioActivity.this);
			fetcher.execute();
        }
    };
    
    final BroadcastReceiver novoConviteReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
        	
        	if (intent.hasExtra(PROPERTY_ID)) {
        		int id = intent.getIntExtra(PROPERTY_ID, 0);
        		
        		Convite convite = new Convite(id);
        		
        		List<Convite> convites = Convite.getConvitesFuturos();
    	        int nConvites = convites.size();
    	        setIconeNotificacao(nConvites);
    	        
	        	Date data = new Date(convite.getHorario());
	            String dataFormatada = new SimpleDateFormat("dd/MM/yyyy HH'h'mm'm'").format(data);
	            
	        	ActionItem nextItem = new ActionItem(convite.getId(), convite.getRestaurante() + " " + dataFormatada, getResources().getDrawable(R.drawable.ic_envelop_w));

	            // setSticky(true) esconde o menu dropdown depois que um item foi clicado
	            nextItem.setSticky(true);
	            
	            // Adiciona item ao menu de dropdown 
	            quickAction.addActionItem(nextItem);
	            
            	Intent newIntent;
            	newIntent = new Intent(context, ConviteActivity.class);
            	newIntent.putExtra("idConvite", id);
        	
            	startActivity(newIntent);
        	}
        }
    };
    
    final BroadcastReceiver respostaConviteReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
        	Intent staterIntent = ConviteActivity.starterIntent;
        	startActivity(staterIntent);
        }
    };
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		this.mFragmentManager = getSupportFragmentManager();

		ActionBar actionBar = this.getSupportActionBar();
		actionBar.setCustomView(R.layout.actionbar);
		actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
		actionBar.setLogo(R.drawable.actionbar_logo);
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
        actionBar.setDisplayHomeAsUpEnabled(false);
        actionBar.setHomeButtonEnabled(true);

        SlidingMenu slidingMenu = getSlidingMenu();
        slidingMenu.setBehindWidthRes(R.dimen.sliding_menu_width);
        slidingMenu.setBehindScrollScale(0.0f);
        slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
        setBehindContentView(R.layout.fragment_menu);
        
        
        setContentView(R.layout.activity_cardapio);
        getSupportFragmentManager().beginTransaction().replace(R.id.frag_menu, new MenuFragment()).commit();
        

    	// Exibe animação de carregamento
        ImageView loaderView = (ImageView)findViewById(R.id.loader);
        loaderView.setBackgroundDrawable(getResources().getDrawable(R.drawable.loading));

        
        MyAnimationRoutine mar = new MyAnimationRoutine();
        Timer timer = new Timer(false);
        timer.schedule(mar, 1000);
        
        
        // Se foram enviados extras para essa activity da tela de registro, 
        // realiza o registro primeiramente 
        Intent i = getIntent();
        
        if (i.hasExtra("nome") && i.hasExtra("fotoCodificada") && i.hasExtra("numeroTelefone")) {
    		String nome = i.getStringExtra("nome");
            String fotoCodificada = i.getStringExtra("fotoCodificada");
            String numeroTelefone = i.getStringExtra("numeroTelefone");
            
        	//Faz-se teste se existe conexão com a internet
        	//Se não houver conexão exibir mensagem de erro e retorna-se a tela anterior
            ConnectionDetector cd = new ConnectionDetector(getApplicationContext());
            
            if (!cd.isConnectingToInternet()) {
    			Toast toast = Toast.makeText(this, R.string.erro_conexao_internet, Toast.LENGTH_LONG);
    			toast.show();
    			
    			Intent newIntent;
            	newIntent = new Intent(this, RegistroActivity.class);
            	newIntent.putExtra("nome", nome);
            	newIntent.putExtra("fotoCodificada", fotoCodificada);
            	newIntent.putExtra("numeroTelefone", numeroTelefone);
    	        startActivity(newIntent);
    			
    			this.finish();
            }
            
            this.registrarDispostivo(nome, fotoCodificada, numeroTelefone);
            
            // Esconde a barra inferior
            View v = findViewById(R.id.buttonlayout);
            v.setVisibility(View.GONE);
        } else {
            // Chama o update do cardápio via internet
        	this.receberCardapio();
        }
        
        //Registra um broadcast receiver de registro de novo "usuário"
        this.registerReceiver(this.registroReceiver, new IntentFilter(GCM_NOTIFICATION_REGISTRO));
        
        //Registra um broadcast receiver de convites
        this.registerReceiver(this.novoConviteReceiver, new IntentFilter(GCM_NOTIFICATION_NOVO_CONVITE));
        
        //Registra um broadcast receiver de respostas de convites
        this.registerReceiver(this.respostaConviteReceiver, new IntentFilter(GCM_NOTIFICATION_RESPOSTA_CONVITE));
        
        // Ao clicar no botão "tentar novamente",
        // reexecutar o get do cardápio da internet
        Button tentarNovamente = (Button) findViewById(R.id.tentar_novamente);
        tentarNovamente.setOnClickListener(new OnClickListener() {
	        
			@Override
			public void onClick(View arg0) {
				CardapioFetcher fetcher = new CardapioFetcher(CardapioActivity.this);
		  		fetcher.execute();
	        }
	    });
        
  		
        // Ao clicar no botão "novo convite",
        // abrir a tela para convidar pessoas para o bandeco
  		Button novoConvite = (Button) findViewById(R.id.novo_convite);
  		novoConvite.setOnClickListener(new OnClickListener() {
	        
			@Override
			public void onClick(View arg0) {
				Intent intent;
    			intent = new Intent(arg0.getContext(), NovoConviteActivity.class);
    	        startActivity(intent);
	        }
	    });
  		
  		// Cria o menu de dropdown para a área de notificações
        quickAction = new QuickAction(this, QuickAction.VERTICAL);

        List<Convite> convites = Convite.getConvitesFuturos();
        
        for (Convite convite : convites) {
        	Date data = new Date(convite.getHorario());
            String dataFormatada = new SimpleDateFormat("dd/MM/yyyy HH'h'mm'm'").format(data);
            
        	ActionItem nextItem = new ActionItem(convite.getId(), convite.getRestaurante() + " " + dataFormatada, getResources().getDrawable(R.drawable.ic_envelop_w));

            // setSticky(true) esconde o menu dropdown depois que um item foi clicado
            nextItem.setSticky(true);
            
            // Adiciona item ao menu de dropdown 
            quickAction.addActionItem(nextItem);
        }
        

        // Modifica o ícone de notificação 
        // dependendo do número de convites pendentes
        this.setIconeNotificacao(convites.size());
        
        // Ao clicar em alguma notificação ir para a tela de um convite 
        quickAction.setOnActionItemClickListener(new QuickAction.OnActionItemClickListener() {          
        	
        	@Override
            public void onItemClick(QuickAction source, int pos, int actionId) {
        		Intent intent;
    			intent = new Intent(getApplicationContext(), ConviteActivity.class);
        		
        		//here we can filter which action item was clicked with pos or actionId parameter
        		ActionItem actionItem = quickAction.getActionItem(pos);                
        		
        		// Busca no banco de dados os dados do convite e dos convidados
        		int idConvite = actionItem.getActionId();
        		
        		intent.putExtra("idConvite", idConvite);
            	
            	startActivity(intent);
        	}
        });

        //set listnener for on dismiss event, this listener will be called only if QuickAction dialog was dismissed
        //by clicking the area outside the dialog.
        quickAction.setOnDismissListener(new QuickAction.OnDismissListener() {          
        	
        	@Override
        	public void onDismiss() {
        		//Toast.makeText(getApplicationContext(), "Dismissed", Toast.LENGTH_SHORT).show();
        	}
        });
        
  		
        // Exibe o menu de dropdown quando clicar no �cone de notificação
  		ImageView notification = (ImageView) actionBar.getCustomView().findViewById(R.id.notification);
  		notification.setOnClickListener(new OnClickListener() {
	        
			@Override
			public void onClick(View arg0) {
				quickAction.show(arg0);
	        }
	    });
	}
	
	class MyAnimationRoutine extends TimerTask {
		MyAnimationRoutine() {
		}
		@Override
		public void run() {
			ImageView img = (ImageView)findViewById(R.id.loader);
			// Get the background, which has been compiled to an AnimationDrawable object.
			AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();
			// Start the animation (looped playback by default).
			frameAnimation.start();
		}
	}
	
	private void registrarDispostivo(String nome, String fotoCodificada, String numeroTelefone) {
     	Context context = getApplicationContext();

        // Check device for Play Services APK. If check succeeds, proceed with
        //  GCM registration.
        if (checkPlayServices()) {
            this.gcm = GoogleCloudMessaging.getInstance(this);
            String regId = getRegistrationId(context);

            if (regId.equalsIgnoreCase("")) {
                registerInBackground(nome, fotoCodificada, numeroTelefone);
            }
        } else {
            Log.i(TAG, "No valid Google Play Services APK found.");
        }
    }
	
	
	private void receberCardapio() {
		CardapioFetcher fetcher = new CardapioFetcher(this);
  		fetcher.execute();
	}
    
    
    public void setIconeNotificacao(int numeroNotificacoes) {
    	ActionBar actionBar = this.getSupportActionBar();
        ImageView iconeNotificacao = (ImageView)actionBar.getCustomView().findViewById(R.id.notification);
        
        System.out.println(numeroNotificacoes + " notificações");
        
        switch (numeroNotificacoes) {
        	case 0:
        		iconeNotificacao.setImageResource(R.drawable.ic_envelop_0);
        		break;
        	case 1:
        		iconeNotificacao.setImageResource(R.drawable.ic_envelop_1);
        		break;
        	case 2:
        		iconeNotificacao.setImageResource(R.drawable.ic_envelop_2);
        		break;
    		default: 
    			iconeNotificacao.setImageResource(R.drawable.ic_envelop_3);
    		break;
        }
    }
	
	private boolean checkPlayServices() {
	    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
	    if (resultCode != ConnectionResult.SUCCESS) {
	        if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
	            GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_RESOLUTION_REQUEST).show();
	        } else {
	            System.out.println("This device is not supported.");
	            finish();
	        }
	        return false;
	    }
	    return true;
	}
	
	private void storeUserData(Context context, int id) {
	    final SharedPreferences prefs = getSharedPreferences("com.bora_bandeco", Context.MODE_PRIVATE);
	    int appVersion = getAppVersion(context);
	    Log.i(TAG, "Saving userId on app version " + appVersion);
	    SharedPreferences.Editor editor = prefs.edit();
	    editor.putInt(PROPERTY_ID, id);
	    editor.putInt(PROPERTY_APP_VERSION, appVersion);
	    editor.commit();
	}
	
	private void storeUserData(Context context, String nome, String fotoCodificada, String numeroTelefone, String regId) {
	    final SharedPreferences prefs = getSharedPreferences("com.bora_bandeco", Context.MODE_PRIVATE);
	    int appVersion = getAppVersion(context);
	    Log.i(TAG, "Saving regId on app version " + appVersion);
	    SharedPreferences.Editor editor = prefs.edit();
	    editor.putString(PROPERTY_NOME, nome);
	    editor.putString(PROPERTY_FOTO_CODIFICADA, fotoCodificada);
	    editor.putString(PROPERTY_NUMERO_TELEFONE, numeroTelefone);
	    editor.putString(PROPERTY_REG_ID, regId);
	    editor.putInt(PROPERTY_APP_VERSION, appVersion);
	    editor.commit();
	}
	
	private String getRegistrationId(Context context) {
	    final SharedPreferences prefs = getSharedPreferences("com.bora_bandeco", Context.MODE_PRIVATE);
	    String registrationId = prefs.getString(PROPERTY_REG_ID, "");
	    if (registrationId.equalsIgnoreCase("")) {
	        Log.i(TAG, "Registration not found.");
	        return "";
	    }
	    // Check if app was updated; if so, it must clear the registration ID
	    // since the existing regID is not guaranteed to work with the new
	    // app version.
	    int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
	    int currentVersion = getAppVersion(context);
	    if (registeredVersion != currentVersion) {
	        Log.i(TAG, "App version changed.");
	        return "";
	    }
	    return registrationId;
	}
	
	private static int getAppVersion(Context context) {
	    try {
	        PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
	        return packageInfo.versionCode;
	    } catch (NameNotFoundException e) {
	        // should never happen
	        throw new RuntimeException("Could not get package name: " + e);
	    }
	}
	
	private void registerInBackground(String nome, String fotoCodificada, String numeroTelefone) {
		
		new AsyncTask<String, Void, String>() {
	        @Override
	        protected String doInBackground(String... params) {
	            String msg = "";
	            String nome = params[0];
	            String fotoCodificada = params[1];
	            String numeroTelefone = params[2];
	            try {
	                if (gcm == null) {
	                    gcm = GoogleCloudMessaging.getInstance(CardapioActivity.this);
	                }
	                String regId = gcm.register(SENDER_ID);
	                msg = "Device registered, registration ID=" + regId;
	                
	                storeUserData(CardapioActivity.this, nome, fotoCodificada, numeroTelefone, regId);
	                
	                // You should send the registration ID to your server over HTTP,
	                // so it can use GCM/HTTP or CCS to send messages to your app.
	                // The request to your server should be authenticated if your app
	                // is using accounts.
	                ServerUtilities.registrarContato(CardapioActivity.this, nome, fotoCodificada, numeroTelefone, regId);
	            } catch (IOException ex) {
	                msg = "Error :" + ex.getMessage();
	                // If there is an error, don't just keep trying to register.
	                // Require the user to click a button again, or perform
	                // exponential back-off.
	            }
	            return msg;
	        }

	        @Override
	        protected void onPostExecute(String msg) {
	            //mDisplay.append(msg + "\n");
	        }
	    }.execute(nome, fotoCodificada, numeroTelefone);
	}


	@Override
	protected void onDestroy() {
		super.onDestroy();
		
        this.unregisterReceiver(this.registroReceiver);
        
        this.unregisterReceiver(this.novoConviteReceiver);
        
        this.unregisterReceiver(this.respostaConviteReceiver);
	}
	
	
}
